package Modele;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;

public class Tour {
	private int annee;
	private String saison;
	private ArrayList<Ordre> listeOrdre;

	public Tour(int annee, String saison) {
		this.annee = annee;
		this.saison = saison;
		this.listeOrdre = new ArrayList<Ordre>();
	}

	public int getAnnee() {
		return annee;
	}

	public int getNextAnnee() {
		if (this.saison.equals("Atomne")) {
			return annee + 1;
		}
		return annee;
	}

	public String getSaison() {
		return saison;
	}

	public String getNextSaison() {
		if (this.saison.equals("Automne")) {
			return "Printemps";
		}
		return "Automne";
	}

	public void addOrdre(Ordre o) {
		this.listeOrdre.add(o);
	}

	public void arbitrage() {
		ArrayList<String> listeOrdreString = new ArrayList<String>();
		listeOrdreString = this.demandeOrdre();
		ArrayList<String> blackList = new ArrayList<String>();
		HashMap<Region, ArrayList<Ordre>> listeConflit = new HashMap<Region, ArrayList<Ordre>>();

		for (String s : listeOrdreString) {
			Ordre o = Ordre.verifSyntaxe(s);
			// Suppression des doublons
			for (Ordre ordre : this.listeOrdre) {
				// Si l'ordre existe deja
				if (o.getRegOrigine().getAbreviation()
						.equalsIgnoreCase(ordre.getRegOrigine().getAbreviation())) {
					blackList.add(o.getRegOrigine().getAbreviation());
					this.listeOrdre.remove(ordre);
				} else if (!blackList.contains(o.getRegOrigine().getAbreviation())) {
					this.listeOrdre.add(o);
				}
			}
		}

		// Ajout des regions sans ordres
		for (String s : Partie.carte.keySet()) {
			// Voir la methode pour comparaison avec la redef de la fonction
			if (Partie.getRegion(s).getOccupant() != null) {
				boolean present = false;
				for (Ordre o : this.listeOrdre) {
					if (Partie.getRegion(s).equals(o.getRegOrigine())) {
						present = true;
					}
				}
				if (!present) {
					// Ajout de l'ordre de tenir position
					this.listeOrdre.add(new Defense(Partie.getRegion(s).getOccupant()
							.getProprietaire(), Partie.getRegion(s).getOccupant().getTypeUnite(),
							Partie.getRegion(s)));
				}
			}
		}

		// Verifcation des croisements
		for (int i = 0; i <= this.listeOrdre.size(); i++) {
			Ordre o = this.listeOrdre.get(i);
			if (o instanceof Attaque) {
				if (!o.isCroisement()) {
					for (int j = i; j < this.listeOrdre.size(); j++) {
						Ordre p = listeOrdre.get(j);
						if (p instanceof Attaque) {
							if (o.getRegOrigine().equals(p.getRegDestination())
									&& o.getRegDestination().equals(p.getRegOrigine())) {
								o.setCroisement(true);
								p.setCroisement(true);
							}
						}
					}
				}
			}
		}

		// Tri de listeOrdre (Convoi - Sout - Def - Att)
		Collections.sort(this.listeOrdre, new Comparator<Ordre>() {
			public int compare(Ordre o1, Ordre o2) {
				String s1 = "";
				if (o1 instanceof Attaque) {
					s1 = "d";
				} else if (o1 instanceof Defense) {
					s1 = "c";
				} else if (o1 instanceof Soutien) {
					s1 = "b";
				} else if (o1 instanceof Convoi) {
					s1 = "a";
				}
				String s2 = "";
				if (o2 instanceof Attaque) {
					s2 = "d";
				} else if (o2 instanceof Defense) {
					s2 = "c";
				} else if (o2 instanceof Soutien) {
					s2 = "b";
				} else if (o2 instanceof Convoi) {
					s2 = "a";
				}

				return s1.compareTo(s2);
			}
		});

		// Verification des ordres
		ArrayList<Ordre> soutienToVerif = new ArrayList<Ordre>();
		for (Ordre o : this.listeOrdre) {
			if (o instanceof Convoi) {
				if (o.verifValidite()) {
					for (Ordre ordre : this.listeOrdre) {
						if (((Convoi) o).getRegionConvoye().equals(ordre.getRegOrigine())) {
							ordre.addConvoi(o);
							break;
						}
					}
				}
				Ordre or = new Defense(o.getCommanditaire(), o.getTypeUnite(), o.getRegOrigine());
				if (listeConflit.containsKey(or.getRegOrigine())) {
					listeConflit.get(or.getRegOrigine()).add(or);
				} else {
					ArrayList<Ordre> oListe = new ArrayList<Ordre>();
					oListe.add(or);
					listeConflit.put(or.getRegOrigine(), oListe);
				}
			} else if (o instanceof Soutien) {
				if (o.verifValidite()) {
					soutienToVerif.add(o);
				} else {
					Ordre or = new Defense(o.getCommanditaire(), o.getTypeUnite(),
							o.getRegOrigine());
					if (listeConflit.containsKey(or.getRegOrigine())) {
						listeConflit.get(or.getRegOrigine()).add(or);
					} else {
						ArrayList<Ordre> oListe = new ArrayList<Ordre>();
						oListe.add(or);
						listeConflit.put(or.getRegOrigine(), oListe);
					}
				}
			} else if (o instanceof Defense) {
				if (listeConflit.containsKey(o.getRegOrigine())) {
					listeConflit.get(o.getRegOrigine()).add(o);
				} else {
					ArrayList<Ordre> oListe = new ArrayList<Ordre>();
					oListe.add(o);
					listeConflit.put(o.getRegOrigine(), oListe);
				}
			} else if (o instanceof Attaque) {
				if (o.verifValidite()) {
					if (listeConflit.containsKey(o.getRegDestination())) {
						listeConflit.get(o.getRegDestination()).add(o);
					} else {
						ArrayList<Ordre> oListe = new ArrayList<Ordre>();
						oListe.add(o);
						listeConflit.put(o.getRegDestination(), oListe);
					}
				} else {
					if (listeConflit.containsKey(o.getRegOrigine())) {
						listeConflit.get(o.getRegOrigine()).add(o);
					} else {
						ArrayList<Ordre> oListe = new ArrayList<Ordre>();
						oListe.add(o);
						listeConflit.put(o.getRegOrigine(), oListe);
					}
				}
			}
		}
		ArrayList<Ordre> toDelete = new ArrayList<Ordre>();
		boolean attaque = false;
		for (Ordre o : soutienToVerif) {
			attaque = false;
			if (listeConflit.containsKey(o.getRegOrigine())) {
				for (Ordre ordre : listeConflit.get(o.getRegOrigine())) {
					if (ordre instanceof Attaque) {
						toDelete.add(ordre);
						attaque = true;
					}
				}
			}
			if (!attaque) {
				for (Ordre ord : this.listeOrdre) {
					if (ord.equals(o)) {
						ord.incrementeForce();
					}
				}
			}
		}
		// Pour chaque Soutient attaque on l'ajoute en tenir position dans son
		// territoire
		for (Ordre o : toDelete) {
			Ordre or = new Defense(o.getCommanditaire(), o.getTypeUnite(), o.getRegOrigine());
			if (listeConflit.containsKey(or.getRegOrigine())) {
				listeConflit.get(or.getRegOrigine()).add(or);
			} else {
				ArrayList<Ordre> oListe = new ArrayList<Ordre>();
				oListe.add(or);
				listeConflit.put(or.getRegOrigine(), oListe);
			}
		}
		// todo : On trie l'hashMap en fonction de la taille ArrayList<Ordre>
		// pour les croisements
		// voir excel
		for (Region region : listeConflit.keySet()) {
			if (listeConflit.get(region).size() == 1) {
				// Ordre
			} else {
				// si ordre.type = defense et force def < force total de toutes
				// les attaques
				// ajout dans arraylist listeRetraite
				// sinon si ordre.type = attaque et ordre.force > forces des
				// autres ordre
				// effectuer action
			}
		}
	}

	public ArrayList<String> demandeOrdre() {
		ArrayList<String> l = new ArrayList<String>();

		l.add("FR A POR - ESP");
		l.add("FR A POR - ESP");
		l.add("FR A POR - ESP");
		l.add("FR A POR - ESP");
		l.add("FR A GAS - BOU");
		l.add("FR A GAS - BOU");
		l.add("FR A GAS - BOU");
		l.add("GB A BOU T");
		l.add("FR A PAR - PIC");
		l.add("FR F MAN S PAR - PIC");
		l.add("GB A BEL S PIC");
		l.add("GB A PIC T");
		l.add("FR A BRE - ATL");
		l.add("FR F ISL - GRO");
		l.add("FR A MAR - NAP");
		l.add("FR F MED C MAR - NAP");
		l.add("FR F TYR C MAR - NAP");
		l.add("FR A VEN - MON");
		l.add("FR F ADR C VEN - MON");
		l.add("FR F BOT - SUE");
		l.add("FR A FIN - STP");
		l.add("FR A MOS S FIN - STP");
		l.add("GB A LIT - MOS");
		l.add("GB A VAR S LIT - MOS");
		l.add("FR A MUN - BOH");
		l.add("GB A BOH T");
		l.add("GB A VIE S BOH");
		l.add("FR A TRI - BUD");
		l.add("FR A GAL S TRI - BUD");
		l.add("FR A UKR - ODE");
		l.add("FR F NOI S UKR - ODE");
		l.add("FR A SER - BUL");
		l.add("FR A ROU S SER - BUL");
		l.add("GB A BUL - GRE");
		l.add("GB A NAP T");
		l.add("GB A STP T");

		return l;
	}
}
